AngularJSとRuby on Railsで作るCRUDアプリ – (4)Update
はじめに
前回構築したAngularJS+Ruby on Railsのアプリに
今回はCRUDの内のUpdate機能を実装し、ウィスキーの情報を更新する画面を作成しました。
画面遷移としては
・一覧画面(index.html.erb)よりリンクをクリックし、今回作成する更新画面(edit.html.erb)に遷移する
・更新画面でボタンを押下すると、AngularJSにより非同期でサーバを呼び出し、更新する
・登録後、AngularJSにより一覧画面に遷移する
となります。
以下に、実装する上でのポイントとなる箇所を記述していきます。
尚、ソースコードは以下のGitHubに置いてあるので、全ソースを見たい方は参考にしてください。
AngularjsWhiskyList
実装について
1.ルーティング
更新画面に表示するデータを取得するためのURLとして、以下のコードをroutes.rbに追記します。
get 'whiskies/:id/detail' => 'whiskies#detail'
$ rake routes でルーティングの確認をすると、以下のようになります。
whiskies_list GET /whiskies/list(.:format) whiskies#list GET /whiskies/:id/detail(.:format) whiskies#detail (中略) edit_whisky GET /whiskies/:id/edit(.:format) whiskies#edit whisky GET /whiskies/:id(.:format) whiskies#show PATCH /whiskies/:id(.:format) whiskies#update PUT /whiskies/:id(.:format) whiskies#update DELETE /whiskies/:id(.:format) whiskies#destroy
今回使用するのは
・更新画面に表示するデータを取得する「GET /whiskies/:id/detail(.:format) whiskies#detail」(2行目)
・更新画面に遷移するための「GET /whiskies/:id/edit(.:format) whiskies#edit」(4行目)
・更新データを送るための「PUT /whiskies/:id(.:format) whiskies#update」(7行目)
です。
2.一覧画面
一覧画面に、更新画面へ遷移するためのリンクと、削除するためのボタンを追加しました。
またTwitter Bootstrapのtableを使い、多少見栄えを良くしています。
(尚、今回は削除ボタンについては触れません)
index.html.erb
<h1>Whiskies#index</h1> <%= link_to "new whisky", new_whisky_path, :class => 'btn btn-mini' %> <table ng-controller="WhiskiesCtrl" class="table"> <tr ng-repeat="whisky in data"> <td>{{whisky.name}}</td> <td>${{whisky.price}}</td> <td><a href="/whiskies/{{whisky.id}}/edit" class="btn btn-mini">Edit</a></td> <td><button ng-click="Delete(whisky);" class="btn btn-mini">Delete</button></td> </tr> </table>
EditリンクのURLの定義は「a href="/whiskies/{{whisky.id}}/edit」となっています。
{{whisky.id}}はAngularJSの式で、{{}}内に記述した変数やプロパティ等の値を参照します。
ここでは一覧に表示するデータのidが取得されるので、実際のURLは以下のような形となります。
/whiskies/2/edit
上記1.で記述した、更新画面に遷移するためのURLを指定していることが分かるかと思います。
3.更新画面
更新画面は以下のようになります。
edit.html.erb
<h1>Whiskies#edit</h1> <div ng-controller="WhiskiesEditCtrl"> <div>Name</div><div><input type="text" ng-model="data.name"></div> <div>Price</div><div><input type="text" ng-model="data.price"></div> <button ng-click='Update();' class="btn-primary">Update</button> </div>
ここでは
・AngularJSの「WhiskiesEditCtrl」コントローラを呼び出す
・テキストボックスに「data.name」「data.price」を初期表示する
・Updateボタン押下時に「Update()」を呼び出す
を行っています。
4.更新処理のAngularJS
更新画面から呼び出されるAngularJSは、以下のようになります。
controllers.js
whiskiesListApp.controller('WhiskiesEditCtrl', function ($scope, $http, $window) { $http.get('detail').success(function(data) { $scope.data = data; }).error(function(data, status) { console.log('error:' + status); }); $scope.Update = function(){ $http.put('/whiskies/' + $scope.data.id, {'name': $scope.data.name, 'price': $scope.data.price} ).success(function(data, status, headers, config) { $window.location.href = '/'; }).error(function(data, status) { console.log('error:' + status); }); } });
更新画面から呼び出される「WhiskiesEditCtrl」コントローラは
・「$http.get('detail').success(function(data) {・・・」のデータ取得処理
・「$scope.Update = function(){・・・」のUpdateボタン押下時の処理
の2つに分かれます。
「$http.get('detail').success(function(data) {・・・」のデータ取得処理は
上記1.で記述した、データを取得するURLを指定しています。
先に説明したように、更新画面自体は「/whiskies/:id/edit」の形で呼び出されています。
このURLの末尾「edit」を「detail」に変えることで、「/whiskies/:id/detail」となり
ルーティングで定義されているデータを取得するためのURLとなります。
「$scope.Update = function(){・・・」のUpdateボタン押下時の処理は
上記1.で記述した、更新データを送るためのURLを指定しています。
ここで注目して欲しいのは、「$http.put」でPUT送信している点です。
PUT送信することで、ルーティングで定義されているデータを更新するためのURLとなります。
※Railsのコントローラのdetail()、update()アクションについては
単純なActiveRecordのソースとなります。詳細はGitHub上のソースを参考にしてください。
最後に
以上です。
AngularJSの$httpオブジェクトを使うことで、Railsのルーティングに即したURLを生成し
処理を行うことができました。